package com.ysw.service.impl;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author: yu_sw 协调类
 * @Description: com.ysw.service.impl
 * @date:2023/4/27 18:28
 */
@Data
public class Coordinator {
    // 事务模板
    TransactionTemplate transactionTemplate;
    CyclicBarrier cyclicBarrier;
    AtomicReference<Boolean> rollback = new AtomicReference<>(Boolean.FALSE);
    ExecutorService executorService = Executors.newFixedThreadPool(20);
    // runnable任务接口可以自己自定义也行
    List<Runnable> taskList = new ArrayList<>();
    public Coordinator(TransactionTemplate transactionTemplate, Runnable callback, Runnable... tasks) {
        this.transactionTemplate = transactionTemplate;
        Collections.addAll(this.taskList, tasks);
        this.cyclicBarrier = new CyclicBarrier(tasks.length, callback);
    }
    public Coordinator(TransactionTemplate transactionTemplate, Runnable... tasks) {
        this.transactionTemplate = transactionTemplate;
        Collections.addAll(this.taskList, tasks);
        this.cyclicBarrier = new CyclicBarrier(tasks.length);
    }
    /**
     * 开始执行
     */
    public void begin() {
        taskList.forEach(e -> {
            executorService.execute(new InnerTask(e));
        });
    }
    private AtomicInteger atomicInteger = new AtomicInteger(1);
    @Data
    @AllArgsConstructor
    class InnerTask implements Runnable {
        Runnable r;
        /**
         * 创造异常情况
         */
        void createException() {
            int i = atomicInteger.getAndAdd(1);
            // 创造异常
            if (i == 10) {
                int m = 1 / 0;
            }
        }
        @Override
        public void run() {
            System.out.println("wait.................................");
            transactionTemplate.executeWithoutResult(transactionStatus -> {
                try {
                    createException();
                    if (rollback.get().equals(Boolean.FALSE)) {
                        r.run();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    rollback.set(Boolean.TRUE);
                } finally {
                    try {
                        System.out.println(Thread.currentThread().getName() + " wait.....");
                        cyclicBarrier.await();
                        System.out.println(Thread.currentThread().getName() + " 释放啦.....");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
                if (rollback.get().equals(Boolean.TRUE)) {
                    System.out.println("要回滚啦");
                    transactionStatus.setRollbackOnly();
                }
            });
        }
    }
}
